import createDOMElement from './createDOMElement'
import mountElement from './mountElement'
import updateNodeElement from './updateNodeElement'
import updateTextNode from './updateTextNode'
import unmountNode from './unmountNode'
import diffComponent from './diffComponent'

export default function diff(virtualDOM, container, oldDOM) {
  // oldDOM存在的话，缓存oldDOM的virtualDOM
  const oldVirtualDOM = oldDOM && oldDOM._virtualDOM
  const oldComponent = oldVirtualDOM && oldVirtualDOM.component
  // 判断oldDOM是否存在
  if(!oldDOM) {
    mountElement(virtualDOM, container)
  } else if (virtualDOM.type !== oldVirtualDOM.type && typeof virtualDOM.type !== 'function') {
    // 新旧virtualDOM类型不同并且新的virtualDOM不是组件
    const newElement = createDOMElement(virtualDOM)
    oldDOM.parentNode.replaceChild(newElement, oldDOM)
  } else if(typeof virtualDOM.type === 'function') {
    // 如果是组件的情况
    diffComponent(virtualDOM, oldComponent, oldDOM, container)
  } else if (oldVirtualDOM && virtualDOM.type === oldVirtualDOM.type) {
    // 新旧virtualDOM的类型相同
    if(virtualDOM.type === 'text') {
      // 文本节点，更新内容到oldDOM上
      updateTextNode(virtualDOM, oldVirtualDOM, oldDOM)
    }else {
      // 元素节点更新，需要传入oldVirtualDOM
      updateNodeElement(oldDOM, virtualDOM, oldVirtualDOM)
    }

    // 1.将拥有key属性的子元素放在一个单独的对象中
    let keyedElements = {}
    for(let i = 0; i < oldDOM.childNodes.length; i++) {
      let domElement = oldDOM.childNodes[i]
      if(domElement.nodeType === 1) {
        // 元素节点
        const key = domElement.getAttribute('key')
        if(key) {
          keyedElements[key] = domElement
        }
      }
    }
    const hasNoKey = Object.keys(keyedElements).length === 0

    if(hasNoKey) {
      // 对比子节点
      virtualDOM.children.forEach((child, index) => {
        diff(child, oldDOM, oldDOM.childNodes[index])
      })
    }else {
      // 2. 循环virtualDOM 的子元素获取子元素的key 属性
      virtualDOM.children.forEach((child, index) => {
        const key = child.props.key
        if(key) {
          const domElement = keyedElements[key]
          if(domElement) {
            // 3. 看看当前位置的元素是不是我们期望的元素
            if(oldDOM.childNodes[index] && oldDOM.childNodes[index] !== domElement) {
              oldDOM.insertBefore(domElement, oldDOM.childNodes[index])
            }
          }else {
            // 新增元素
            mountElement(child, oldDOM, oldDOM.childNodes[index])
          }
        }
      })
    }
    
    // 删除节点
    // 获取旧节点
    const oldChildNodes = oldDOM.childNodes
    // 判断旧节点数量
    const oldChildNodesLength = oldChildNodes.length
    const virtualDOMNodesLength = virtualDOM.children.length
    if (oldChildNodesLength > virtualDOMNodesLength) {
      if(hasNoKey) {
        // 有节点需要被删除
        for(let i = oldChildNodesLength -1; i > virtualDOMNodesLength -1; i--) {
          unmountNode(oldChildNodes[i])
        }
      }else {
        // 通过key属性删除节点
        for(let i = 0; i < oldChildNodes.length; i++) {
          const oldChild = oldChildNodes[i]
          const oldChildKey = oldChild._virtualDOM.props.key
          let found = false
          for(let j = 0; j < virtualDOM.children.length; j++) {
            if(oldChildKey === virtualDOM.children[j].props.key) {
              found = true
              break
            }
          }
          if(!found) {
            unmountNode(oldChild)
          }
        }
      }
    }
  }
}